// Virtual DOM 是否为函数类型
export function isFunction(virtualDOM) {
  return virtualDOM && typeof virtualDOM.type === 'function';
}

// Virtual DOM 是否为函数型组件
// 条件有两个:  1. Virtual DOM 的 type 属性值为函数
//            2. 函数的原型对象中不能有render方法，只有类组件的原型对象中有render方法
export function isFunctionalComponent(virtualDOM) {
  const type = virtualDOM && virtualDOM.type;
  return type && isFunction(virtualDOM) && !(type.prototype && type.prototype.render);
}

// 卸载 真实 dom
export function unMountNode(dom) {
  // 1. 如果要删除的节点是文本节点的话可以直接删除
  // 2. 如果要删除的节点由组件生成，需要调用组件卸载生命周期函数
  // 3. 如果要删除的节点中包含了其他组件生成的节点，需要调用其他组件的卸载生命周期函数
  // 4. 如果要删除的节点身上有 ref 属性，还需要删除通过 ref 属性传递给组件的 DOM 节点对象
  // 5. 如果要删除的节点身上有事件，需要删除事件对应的事件处理函数

  // 获取节点对应的 virtualDOM 对象
  const virtualDOM = dom._virtualDOM;

  // 如果要删除的节点时文本
  if (virtualDOM.type === 'text') {
    // 直接删除节点
    dom.remove();
    // 阻止程序向下运行
    return;
  }

  // 查看节点是否由组件生成
  let component = virtualDOM.component;

  // 如果由组件生成
  if (component) {
    // 调用组件卸载生命周期函数
    component.componentWillUnmount();
  }

  // 如果节点具有 ref 属性 通过再次调用 ref 方法 将传递给组件的DOM对象删除
  if (virtualDOM.props && virtualDOM.props.ref) {
    virtualDOM.props.ref(null);
  }

  // 事件处理
  Object.keys(virtualDOM.props).forEach((propName) => {
    if (propName.slice(0, 2) === 'on') {
      const eventName = propName.toLowerCase().slice(2);
      const eventHandler = virtualDOM.props[propName];
      dom.removeEventListener(eventName, eventHandler);
    }
  });

  // 递归删除子节点
  if (dom.childNodes.length > 0) {
    for (let i = 0; i < dom.childNodes.length; i++) {
      unMountNode(dom.childNodes[i]);
      i--;
    }
  }

  dom.remove();
}

// 判断 否是同一个组件
export function isSameComponent(virtualDOM, oldComponent) {
  return oldComponent && virtualDOM.type === oldComponent.constructor;
}
